package com.zeyu.framework.core.persistence.table;

import com.zeyu.framework.tools.report.dynamic.ReportUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;

import java.io.Serializable;

/**
 * The Class Field.
 */
public class Field implements Serializable {

    /**
     * 报表表格字段类型.
     *
     * @author zeyuphoenix
     */
    public enum FieldType {

        /** 角度，就是横轴（一般是时间、名称等）. */
        /**
         * 默认字符串类型
         */
        ANGLE,

        /** 指标，就是纵轴（一般是数值大小）. */
        /**
         * 默认数字类型
         */
        QUOTA,

        FieldType, /**
         * 其它待扩展,默认字符串类型.
         */
        OTHER
    }

    /**
     * 字段名.
     */
    private String fieldName;

    /**
     * 显示名.
     */
    private String displayName;

    /**
     * 表格字段类型.
     */
    private FieldType fieldType;

    /**
     * 默认按照FieldType进行解析，也可以自己设置.
     */
    private Class<?> filedClass;

    /**
     * 列单元格渲染器，默认角度不渲染，指标使用 packetTransform 渲染，可以自己设置.
     */
    private Render render;

    /**
     * Instantiates a new field.
     *
     * @param fieldName the field name
     * @param fieldType the field type
     */
    public Field(String fieldName, FieldType fieldType) {
        super();
        this.fieldName = fieldName;
        this.fieldType = fieldType;
    }

    /**
     * Instantiates a new field.
     *
     * @param fieldName   the field name
     * @param displayName the display name
     * @param fieldType   the field type
     */
    public Field(String fieldName, String displayName, FieldType fieldType) {
        super();
        this.fieldName = fieldName;
        this.displayName = displayName;
        this.fieldType = fieldType;
    }

    /**
     * Gets the field name.
     *
     * @return the field name
     */
    public String getFieldName() {
        return fieldName;
    }

    /**
     * Sets the field name.
     *
     * @param fieldName the new field name
     */
    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    /**
     * Gets the field type.
     *
     * @return the field type
     */
    public FieldType getFieldType() {
        return fieldType;
    }

    /**
     * Sets the field type.
     *
     * @param fieldType the new field type
     */
    public void setFieldType(FieldType fieldType) {
        this.fieldType = fieldType;
    }

    /**
     * Gets the filed class.
     *
     * @return the filed class
     */
    public Class<?> getFiledClass() {
        if (filedClass == null) {
            if (FieldType.ANGLE == fieldType) {
                return String.class;
            } else if (FieldType.QUOTA == fieldType) {
                return Number.class;
            } else {
                return String.class;
            }
        }
        return filedClass;
    }

    /**
     * Sets the filed class.
     *
     * @param filedClass the new filed class
     */
    public void setFiledClass(Class<?> filedClass) {
        this.filedClass = filedClass;
    }

    /**
     * Gets the render.
     *
     * @return the render
     */
    public Render getRender() {
        if (render == null) {
            if (FieldType.QUOTA == fieldType) {
                Render defRender = new Render("packetTransform");
                defRender.setParameterTypes(new Class<?>[]{Number.class});
                return defRender;
            }
        }
        return render;
    }

    /**
     * Sets the render.
     *
     * @param render the new render
     */
    public void setRender(Render render) {
        this.render = render;
    }

    /**
     * Gets the display name.
     *
     * @return the display name
     */
    public String getDisplayName() {
        if (StringUtils.isEmpty(displayName)) {
            return fieldName;
        }
        return displayName;
    }

    /**
     * Sets the display name.
     *
     * @param displayName the new display name
     */
    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    /**
     * 列单元格的渲染器.
     *
     * @author zeyuphoenix
     */
    public static class Render {

        /**
         * 渲染方法的类名，不设置则是StringUtils.
         */
        private Class<?> cls = ReportUtils.class;

        /**
         * The method name.
         */
        private String methodName;

        /**
         * The args.
         */
        private Object[] args;

        /**
         * The parameter types.
         */
        private Class<?>[] parameterTypes;

        /**
         * Instantiates a new render.
         *
         * @param methodName the method name
         */
        public Render(String methodName) {
            super();
            this.methodName = methodName;
        }

        /**
         * Gets the cls.
         *
         * @return the cls
         */
        public Class<?> getCls() {
            return cls;
        }

        /**
         * Sets the cls.
         *
         * @param cls the new cls
         */
        public void setCls(Class<?> cls) {
            this.cls = cls;
        }

        /**
         * Gets the method name.
         *
         * @return the method name
         */
        public String getMethodName() {
            return methodName;
        }

        /**
         * Sets the method name.
         *
         * @param methodName the new method name
         */
        public void setMethodName(String methodName) {
            this.methodName = methodName;
        }

        /**
         * Gets the args.
         *
         * @return the args
         */
        public Object[] getArgs() {
            return args;
        }

        /**
         * Sets the args.
         *
         * @param args the new args
         */
        public void setArgs(Object[] args) {
            this.args = args;
        }

        /**
         * Gets the parameter types.
         *
         * @return the parameter types
         */
        public Class<?>[] getParameterTypes() {
            if (parameterTypes == null) {
                return new Class<?>[]{Number.class};
            }
            return parameterTypes;
        }

        /**
         * Sets the parameter types.
         *
         * @param parameterTypes the new parameter types
         */
        public void setParameterTypes(Class<?>[] parameterTypes) {
            this.parameterTypes = parameterTypes;
        }

        /*
         * (non-Javadoc)
         *
         * @see java.lang.Object#toString()
         */
        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}